package org.exia.minisig.swing.view.navigation;

import java.awt.Cursor;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.event.MouseWheelEvent;
import java.awt.event.MouseWheelListener;
import java.io.IOException;

import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JLabel;
import javax.swing.JPanel;

import org.exia.minisig.application.Utils;
import org.exia.minisig.model.object.Interest;
import org.exia.minisig.model.object.Place;

@SuppressWarnings("serial")
public class MapComponent extends JComponent implements MouseWheelListener, MouseMotionListener, MouseListener  {
	//VAR
	private JLabel tootips;
	private Image redPoi;
	private Image bluePoi;
	private Place map;
	private Point mapLocation;
	private float zoomRate = (float) 0.5;
	private boolean draggable = true;  
	protected Point anchorPoint;   
    protected Cursor draggingCursor = Cursor.getPredefinedCursor(Cursor.HAND_CURSOR);   
	private JPanel containers;
	private boolean waitClic;
	private NavigationFram parent;
    //GET & SET
	public boolean isWaitClic() {
		return waitClic;
	}
	public void setWaitClic(boolean waitClic) {
		this.waitClic = waitClic;
	}
	public void setMap(Place _map){
		this.map = _map;
	}
	public Place getMap(){
		return this.map;
	}
	public float getZoomRate() {
		return zoomRate;
	}
	public void setZoomRate(float zoomRate) {
		this.zoomRate = zoomRate;
	}
	public Point getMapLocation() {
		return mapLocation;
	}
	public void setMapLocation(Point mapLocation) {
		this.mapLocation = mapLocation;
	}
	//CONSTRUCTOR
	public MapComponent(NavigationFram _parent, Place _map, JPanel _containers, JButton zoomUp, JButton zoomDown){
		initializeVar(_parent, _map, _containers, zoomUp, zoomDown);
	}

	public void initializeVar(NavigationFram _parent, Place _map, JPanel _containers, JButton zoomUp, JButton zoomDown){
		this.tootips = new JLabel();
		try {
			bluePoi = ImageIO.read( getClass().getResource( "/images/navigation/poi_blue.png" ) );
			redPoi = ImageIO.read( getClass().getResource( "/images/navigation/poi_red.png" ) );
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
		}
		//
		this.hoverElement = null;
		this.parent = _parent;
		//
		this.addMouseListener(this);
		this.waitClic = false;
		this.addMouseMotionListener(this);
		//
		this.addMouseWheelListener(this);
		//		
		zoomUp.addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				if (zoomRate < 1){
					zoomRate = (float) (zoomRate + 0.1);
				}
			}
		});
		zoomDown.addActionListener(new ActionListener() {
			
			@Override
			public void actionPerformed(ActionEvent e) {
				if (zoomRate > 0.2){
					zoomRate = (float) (zoomRate - 0.1);
				}
			}
		});
		//
		this.containers = _containers;
		this.map = _map;
		this.mapLocation = new Point(0,0);
		//
        addDragListeners();
	}
	//METHODE
    private void addDragListeners() {
        addMouseMotionListener(new MouseAdapter() {
            @Override
            public void mouseMoved(MouseEvent e) {
                anchorPoint = e.getPoint();
                setCursor(Cursor.getPredefinedCursor(Cursor.HAND_CURSOR));
            }
            @Override
            public void mouseDragged(MouseEvent e) {
                int anchorX = anchorPoint.x;
                int anchorY = anchorPoint.y;

                Point parentOnScreen = getParent().getLocationOnScreen();
                Point mouseOnScreen = e.getLocationOnScreen();
                Point position = new Point(mouseOnScreen.x - parentOnScreen.x - anchorX, mouseOnScreen.y - parentOnScreen.y - anchorY);
                //test pour eviter le deplacement hors map negatif
                Point newPosition = new Point(0, 0);
                if (position.x < 0){
                	newPosition.x = position.x;
                }
                if (position.y < 0){
                	newPosition.y = position.y;
                }
                //test pour eviter le deplacement hors map positif
                if (map.getMap().getWidth(null) * zoomRate > containers.getWidth()){
	                if (map.getMap().getWidth(null) * zoomRate < containers.getWidth() + (position.x * -1)){
	                	newPosition.x = (((int)(map.getMap().getWidth(null) * zoomRate) - containers.getWidth()) * -1);
	                }
                }else {
                	newPosition.x = 0;
                }
                if (map.getMap().getHeight(null) * zoomRate  > containers.getHeight()){
	                if (map.getMap().getHeight(null) * zoomRate < containers.getHeight() + (position.y * -1)){
	                	newPosition.y = ((int)(map.getMap().getHeight(null) * zoomRate) - containers.getHeight()) * -1;
	                }
                } else {
                	newPosition.y = 0;
                }
                	
                setLocation(newPosition);
            }
        });
    }
    private void removeDragListeners() {
        for (MouseMotionListener listener : this.getMouseMotionListeners()) {
            removeMouseMotionListener(listener);
        }
        setCursor(Cursor.getDefaultCursor());
    }
    public boolean isDraggable() {
        return draggable;
    }
    public void setDraggable(boolean draggable) {
        this.draggable = draggable;
        if (draggable) {
            addDragListeners();
        } else {
            removeDragListeners();
        }

    }
    public Cursor getDraggingCursor() {
        return draggingCursor;
    }
    public void setDraggingCursor(Cursor draggingCursor) {
        this.draggingCursor = draggingCursor;
    }
    //OVERRIDE
    //---test-----------------------------------//
	@Override
	public void paintComponent(Graphics g){
		//******DESSIN MAP
		g.drawImage(Utils.scaleImage((int)(this.map.getMap().getWidth(null)), (int)(this.map.getMap().getHeight(null)), this.map.getMap(), zoomRate), 
				mapLocation.x, mapLocation.y,
				(int)(this.map.getMap().getWidth(null)*zoomRate), (int)(this.map.getMap().getHeight(null)*zoomRate), 
				null);
		//******DESSIN POI
		for (Interest poi: map.getInterests()) {
				Point position  = new Point(0, 0);
				
				position.x = (int)(poi.getX() * zoomRate) - (bluePoi.getWidth(null) /2) ; 
				position.y = (int)(poi.getY() * zoomRate) - bluePoi.getHeight(null);
				poi.setRealPosition(position);
				
				
				boolean draw = false;
				if (selectedElement != null){
					if (poi.getX() == selectedElement.getX() && poi.getY() == selectedElement.getY()){
						g.drawImage(redPoi,position.x, position.y,null);
						draw = true;
					}
				} 
				if (!draw){
					g.drawImage(bluePoi,position.x, position.y,null);
				}				
		}
	 }
	@Override
	public void mouseWheelMoved(MouseWheelEvent e) {
		int notches = e.getWheelRotation();
		if (notches > 0 && zoomRate > 0.2) {
            zoomRate = (float) (zoomRate - 0.1);
            if ((int)(this.map.getMap().getWidth(null)*zoomRate) < containers.getWidth()){
            	this.setLocation(0, 0);
            }
            if ((int)(this.map.getMap().getHeight(null)*zoomRate) < containers.getHeight()){
            	this.setLocation(0, 0);
            }
		}
        if (notches < 0 && zoomRate < 1) {
        	zoomRate = (float) (zoomRate + 0.1);
        	
        }
	}
	@Override
	public void mouseDragged(MouseEvent e) {
		// TODO Auto-generated method stub
		
	}
	@Override
	public void mouseMoved(MouseEvent e) {
		//*******Pour le placement de la POI
		if(waitClic){  
			parent.reloadPositionDisplay(e.getPoint());
		}
		//*******Pour la selection de la POI
		for (Interest element : map.getInterests()) {
			Point positionPOI = new Point();
			positionPOI.x = (int)(element.getX() * zoomRate) - (bluePoi.getWidth(null) /2) ; 
			positionPOI.y = (int)(element.getY() * zoomRate) - bluePoi.getHeight(null);
			Point positionMouse = e.getPoint();
			//////////
			boolean vertical = false;
			if (positionMouse.x > positionPOI.x && positionMouse.x < (positionPOI.x + 28)){
				vertical = true;
			}
			boolean horizontal = false;
			if (positionMouse.y > positionPOI.y && positionMouse.y < (positionPOI.y + 43)){
				horizontal = true;
			}
			///////////
			if (horizontal && vertical) {
				hoverElement = element;
			} 
		}
		
	}
	private Interest hoverElement;
	private Interest selectedElement;
	
	public Interest getSelectedElement() {
		return selectedElement;
	}
	public void setSelectedElement(Interest selectedElement) {
		this.selectedElement = selectedElement;
	}
	@Override
	public void mouseClicked(MouseEvent e) {
		if (waitClic){
			waitClic = false;
		} else {
		if (hoverElement != null){
			selectedElement = hoverElement;
			parent.setSelectedElement(selectedElement);
		} else {
			parent.setSelectedElement(null);
			selectedElement = null;
		}
		}
	}
	@Override
	public void mouseEntered(MouseEvent e) {
	}
	@Override
	public void mouseExited(MouseEvent e) {
	}
	@Override
	public void mousePressed(MouseEvent e) {
	}
	@Override
	public void mouseReleased(MouseEvent e) {
	}
}
 